Итак, настало время разобраться, как должны быть организованы классы для реализации интерфейсов типа IUnknown и IClassFactory. Вот. Первое, мы должны завести класс наследуемый интерфейс IUnkonwn. Вот например так.
class IMath : public IUnknown
{
public:
STDMETHOD(Add) ( long, long, long* ) PURE;
STDMETHOD(Subtract) ( long, long, long* ) PURE;
STDMETHOD(Multiply) ( long, long, long* ) PURE;
STDMETHOD(Divide) ( long, long, long* ) PURE;
};
Отдельно можно объвить класс со специальными функциями.
class IAdvancedMath : public IUnknown
{
public:
STDMETHOD(Factorial)( short, long* ) PURE;
STDMETHOD(Fibonacci)( short, long* ) PURE;
};
Вот теперь унаследуем эти классы в новый класс и реализуем методы от наследуемых классов.
class Math :
public IMath,
public IAdvancedMath
{
........
};
Кроме этого нам необходим класс фабрики классов IClassFactory, объявить его можно примерно так.
class MathClassFactory : public IClassFactory
{
protected:
long m_lRef;
public:
MathClassFactory();
~MathClassFactory();
// IUnknown
STDMETHOD( QueryInterface(REFIID, void** ));
STDMETHOD_(ULONG, AddRef());
STDMETHOD_(ULONG, Release());
// IClassFactory
STDMETHOD(CreateInstance)(LPUNKNOWN, REFIID, void**);
STDMETHOD(LockServer)(BOOL);
};
Как видите, что здесь даже нет упоминания о классах объявленных ранее. Но это упоминание есть в методе CreateInstance
STDMETHODIMP MathClassFactory::CreateInstance
( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
{
Math* pMath;
HRESULT hr;
*ppvObj = 0;
pMath = new Math;
..............
}
Лично я, например, потратил довольно много времени, чтобы осознать, что интерфейс IUnknown наследуется, а IClassFactory как бы в стороне, и в одном из методов просто создает объект класса унаследованного от IUnknown.
Далее при регистрации классов создается объект фабрики классов, который и создает непосредственно наш класс.
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void** ppv )
{
MathClassFactory *pCF;
.......
pCF = new MathClassFactory;
.......
}